<template>
  <div class="scroll-container" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave" :style="containerStyle">
    <div ref="contentRef" class="scroll-content" :style="contentStyle">
      <div v-for="(item, index) in duplicatedList" :key="index" class="scroll-item">
        <slot :item="item">{{ item }}</slot>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, onUnmounted, nextTick, type CSSProperties } from 'vue'

interface Props {
  list: any[]
  speed?: number
  direction?: 'horizontal' | 'vertical'
  pauseOnHover?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  speed: 50,
  direction: 'vertical',
  pauseOnHover: true,
})

const contentRef = ref<HTMLDivElement | null>(null)
const isPaused = ref(false)
const scrollPosition = ref(0)
const contentSize = ref(0)
const animationFrame = ref<number | null>(null)

// 生成双倍内容用于无缝衔接
const duplicatedList = computed(() => [...props.list, ...props.list])

// 容器样式
const containerStyle = computed<CSSProperties>(() => ({
  overflow: 'hidden',
  position: 'relative',
  width: '100%',
  height: '100%',
}))

// 内容样式
const contentStyle = computed<CSSProperties>(() => ({
  display: 'flex',
  flexDirection: props.direction === 'vertical' ? 'column' : 'row',
  position: 'absolute',
  transition: 'none',
  willChange: 'transform',
  transform: props.direction === 'horizontal' ? `translateX(-${scrollPosition.value}px)` : `translateY(-${scrollPosition.value}px)`,
}))

// 更新内容尺寸
const updateContentSize = () => {
  if (!contentRef.value) return

  if (props.direction === 'horizontal') {
    contentSize.value = contentRef.value.scrollWidth / 2
  } else {
    contentSize.value = contentRef.value.scrollHeight / 2
  }
}

// 动画循环
const animate = () => {
  if (!isPaused.value) {
    const delta = props.speed / 60
    scrollPosition.value += delta

    if (scrollPosition.value >= contentSize.value) {
      scrollPosition.value = 0
    }
  }

  animationFrame.value = requestAnimationFrame(animate)
}

// 事件处理
const handleMouseEnter = () => {
  if (props.pauseOnHover) isPaused.value = true
}

const handleMouseLeave = () => {
  if (props.pauseOnHover) isPaused.value = false
}

// 生命周期
onMounted(() => {
  updateContentSize()
  animate()
})

onUnmounted(() => {
  if (animationFrame.value) {
    cancelAnimationFrame(animationFrame.value)
  }
})

// 监听变化
watch(
  () => props.list,
  () => {
    nextTick(updateContentSize)
  },
)

watch(
  () => props.direction,
  () => {
    nextTick(updateContentSize)
  },
)
</script>

<style scoped>
.scroll-container {
  overflow: hidden;
  position: relative;
}

.scroll-content {
  display: flex;
  position: absolute;
  will-change: transform;
}

.scroll-item {
  flex-shrink: 0;
}
</style>
